package com.yixuan.mt.core.handler;

import com.yixuan.mt.common.cache.BucketsCache;
import com.yixuan.mt.common.cache.PoliciesCache;
import com.yixuan.mt.common.constant.BucketsConstant;
import com.yixuan.mt.common.pojo.PoliciesCachedData;
import com.yixuan.mt.common.utitls.AdminTokenUtils;
import com.yixuan.mt.core.response.FixedResponse;
import io.jsonwebtoken.Claims;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@ChannelHandler.Sharable
public class BeforeControllerHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    BucketsCache bucketsCache;

    @Autowired
    PoliciesCache policiesCache;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            // 获取桶名
            int pos = request.uri().indexOf("/", 1);
            if (pos == -1) {
                FixedResponse.sendNotFoundResponse(ctx);
                ctx.close();
                return;
            }
            String bucketName = request.uri().substring(1, pos);
            // 判断桶是否存在
            if (!bucketsCache.isBucketExist(bucketName)) {
                FixedResponse.sendNotFoundResponse(ctx);
                ctx.close();
                return;
            }
            // 根据访问策略
            switch (bucketsCache.getBucketAccessPolicy(bucketName)) {
                case BucketsConstant.BUCKET_ACCESS_POLICY_PUBLIC: {
                    // 放行
                    ctx.fireChannelRead(msg);
                    break;
                }
                case BucketsConstant.BUCKET_ACCESS_POLICY_PRIVATE: {
                    String authorization = request.headers().get("Authorization");
                    if (authorization == null) {
                        FixedResponse.sendUnauthorizedResponse(ctx);
                        ctx.close();
                        return;
                    }
                    String token = authorization.substring(7);
                    try {
                        Claims claims = AdminTokenUtils.parseJwt(token);
                        Integer id = (Integer) claims.get("id");
                        // 鉴权
                        if (!policiesCache.check(id, request.method().name(), request.uri())) {
                            FixedResponse.sendForbiddenResponse(ctx);
                            ctx.close();
                            return;
                        }
                        // 放行
                        ctx.fireChannelRead(msg);
                    } catch (Exception e) {
                        FixedResponse.sendUnauthorizedResponse(ctx);
                        ctx.close();
                        e.printStackTrace();
                    }
                }
            }
        } else {
            if (ctx.channel().isActive()) {
                ctx.fireChannelRead(msg);
            }
        }
    }
}
